package cn.zsc.netdisk.config;

import cn.zsc.netdisk.common.UserInfo;
import cn.zsc.netdisk.exception.IllegalPasswordException;
import cn.zsc.netdisk.exception.UserAccountNotFoundException;
import cn.zsc.netdisk.handler.AuthenticationProviderHandler;
import cn.zsc.netdisk.handler.PasswordEncoderHandler;
import cn.zsc.netdisk.pojo.User;
import cn.zsc.netdisk.response.Code;
import cn.zsc.netdisk.response.Result;
import cn.zsc.netdisk.service.UserService;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.password.PasswordEncoder;

/**
 * @author ccying
 * @date 2021/2/4
 */
@Configuration
@EnableWebSecurity
@Slf4j
public class MyAuthenticationConfigurer extends WebSecurityConfigurerAdapter {
    private final PasswordEncoderHandler passwordEncoder;
    private final AuthenticationProviderHandler authenticationProvider;
    private final UserService userService;
    private String uid;

    MyAuthenticationConfigurer(PasswordEncoderHandler passwordEncoder, AuthenticationProviderHandler authenticationProvider, UserService userService) {
        this.passwordEncoder = passwordEncoder;
        this.authenticationProvider = authenticationProvider;
        this.userService = userService;
    }

    @Bean
    public PasswordEncoder encoder() {
        return passwordEncoder;
    }

    @Override
    public void configure(AuthenticationManagerBuilder auth) {
        auth.authenticationProvider(authenticationProvider);
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests().antMatchers("/sign-up/**").permitAll()
                .and().authorizeRequests().antMatchers("/file/share/**").permitAll()
                .and().authorizeRequests().antMatchers("/file/download/**").permitAll()
                .and().authorizeRequests().antMatchers("/send").permitAll()
                .and().authorizeRequests().antMatchers("/reset-password").permitAll()
                .and().authorizeRequests().antMatchers("/").permitAll()
                .and().authorizeRequests().antMatchers("/logout").permitAll()
                .and().authorizeRequests().anyRequest().authenticated()
                .and().cors().and().csrf().disable();

        http.formLogin().permitAll().loginProcessingUrl("/")
                .usernameParameter("username").passwordParameter("password")
                .successHandler((request, response, authentication) -> {
                    log.info("登录成功");
                    response.setContentType("application/json;charset=utf-8");
                    User user = userService.authentication();
                    this.uid = user.getUid();
                    response.getWriter().write(JSON.toJSONString(Result.success(user)));
                })
                .failureHandler((request, response, exception) -> {
                    response.setContentType("application/json;charset=utf-8");
                    if (exception instanceof UserAccountNotFoundException) {
                        log.error("用户账号不存在");
                        response.getWriter().write(JSON.toJSONString(Result.fail(Code.USER_ACCOUNT_NOT_FOUND)));
                    } else if (exception instanceof IllegalPasswordException) {
                        log.error("账号密码错误");
                        response.getWriter().write(JSON.toJSONString(Result.fail(Code.USER_ACCOUNT_PASSWORD_ERROR)));
                    }
                })
                .and().exceptionHandling().authenticationEntryPoint((request, response, exception) -> {
                    log.error("未登录授权");
                    response.setContentType("application/json;charset=utf-8");
                    response.getWriter().write(JSON.toJSONString(Result.fail(Code.USER_NOT_SIGN_IN)));
                })
                .and().logout().permitAll()
                .logoutUrl("/logout").logoutSuccessHandler((request, response, authentication) -> {
                    log.info(String.format("用户账号【%s】退出登录", uid));
                    uid = null;
                    response.setContentType("application/json;charset=utf-8");
                    response.getWriter().write(JSON.toJSONString(Result.success()));
                }).invalidateHttpSession(true);
    }
}